/**
*******************************************************
*@file  AS8510.c 
*@brief AS8510.c
*@author 花满楼
*@date     2019-5-24 
*@version  V2
*@note 
	AS8510的具体款式是I1500，电流采样范围1500A，PGA gain是默认设置是25，我更改为5
	在gain是25的时候，输入最大电压50mV，在gain是5时，输入最大250mV，在gain是1时，估计输入时1.25V（企图设置gain=1，但采样出现混乱）
	系统采样存在固定偏差1%，怀疑可能是电压发生器的误差，等上机之后具体调试
	参见P10\P11页码
*******************************************************
*/
#include "AS8510.h"
#include "spi.h"
#include "delay.h"
#include "usart.h"
#include "data.h"
#include "math.h"

#define Filter_Num 5    /**<滑动滤波数值个数*/

u8 Ins_Count = 0;   /**<绝缘检测状态机转换*/
float Ins_Det_P, Ins_Det_M; /**<上电正和负极的绝缘检测*/
float Ins_U1_P1, Ins_U1_N1; /**<主函数中的绝缘检测值*/
float Reg_VP1[Filter_Num], Reg_VP2[Filter_Num], Reg_VN1[Filter_Num], Reg_VN2[Filter_Num], Reg_IP[Filter_Num], Reg_IN[Filter_Num];	
u8 Count_VP1=0,Count_VP2=0,Count_VN1=0,Count_VN2=0,Count_IP=0,Count_IN=0;/**<滑动滤波计数寄存器*/
/**定义一个枚举变量，用于控制AS8510的CS引脚*/
typedef enum 
{
  CS_EN       = 0,
  CS_DIS      = 1,
} AS8510_StatusTypeDef;

/** 
*******************************************************
*@brief 初始化4路电压采样，2路电流采样 
*@param   none
*@return  none
*@note    none
*******************************************************
*/
void AS8510_Init(void)
{
//   u8 temp;
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOE_CLK_ENABLE();           //使能GPIOE时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();           //使能GPIOF时钟
    __HAL_RCC_GPIOI_CLK_ENABLE();           //使能GPIOI时钟
    __HAL_RCC_GPIOH_CLK_ENABLE();           //使能GPIOH时钟
    __HAL_RCC_GPIOG_CLK_ENABLE();           //使能GPIOH时钟
    //PE4
    GPIO_Initure.Pin = GPIO_PIN_11;          //PE11
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;        //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FAST;   //快速
    HAL_GPIO_Init(GPIOE, &GPIO_Initure);    //初始化
    GPIO_Initure.Pin = GPIO_PIN_5;          //PH5
    HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    GPIO_Initure.Pin = GPIO_PIN_0;          //PI0
    HAL_GPIO_Init(GPIOI, &GPIO_Initure);    //初始化
    GPIO_Initure.Pin = GPIO_PIN_8;          //PI0
    HAL_GPIO_Init(GPIOG, &GPIO_Initure);    //初始化
    AS5810_VP_CS = CS_DIS;                        //SPI
    AS5810_VN_CS = CS_DIS;
    AS5810_IP_CS = CS_DIS;
    AS5810_IN_CS = CS_DIS;
    SPI_Init();
    SPI4_SetSpeed(SPI_BAUDRATEPRESCALER_128);    //设置为45M时钟,高速模式,原为2分频 电流
    SPI5_SetSpeed(SPI_BAUDRATEPRESCALER_128);    //设置为45M时钟,高速模式,原为2分频 电压2路
    SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_128);    //设置为45M时钟,高速模式,原为2分频  电流1
    SPI6_SetSpeed(SPI_BAUDRATEPRESCALER_128);    //设置为45M时钟,高速模式,原为2分频  电流2
    AS8510_V_Write();       //初始设置
    AS8510_VB_Write();      //初始设置
    AS8510_I_Write();       //初始设置
    AS8510_Ins_Write();     //初始设置
}

/** 
*******************************************************
*@brief 采集正string的电池侧电压值、负荷侧电压值
*@param   none
*@return  none
*@note    none
*******************************************************
*/
void Rack_VP_Read(u16 *REG_VP, float *Load_VP)
{
    u8 datatemp[10];
    s16 temp_v, temp_i, temp_i_reg, temp_v_reg;
    float total_v1;
    u8 i;
	
		
    AS8510_V_Read(datatemp, 0x84, 0x01);         	/*电压采集*/       
    delay_us(15);
	
	/*根据采集的数值，进行相位换算，并进行相位处理*/
    if ((datatemp[0] & 0x80) != 0)
    {
        AS8510_V_Read(datatemp, 0x80, 0x04);                
        temp_i = datatemp[0] << 8 | datatemp[1];

        if ((datatemp[0] & 0x80) != 0)
            temp_i_reg = (temp_i) & 0x7FFF;
        else
            temp_i_reg = (~temp_i) & 0x7FFF;

        Reg_VP1[Count_VP1++] = (float) temp_i_reg / 32767 * 1.225f * 6452.61f;   //（4M+620）/620=6452.61   
        
        if(Count_VP1>=Filter_Num)/*数组地址*/
            Count_VP1 = 0;
        
        total_v1 = 0;       
        for(i=0;i<Filter_Num;i++)
            total_v1 += Reg_VP1[i];        
        
        *REG_VP = (u16) (total_v1/Filter_Num);

        temp_v = datatemp[2] << 8 | datatemp[3];

        if ((datatemp[2] & 0x80) != 0)
            temp_v_reg = (temp_v) & 0x7FFF;
        else
        {
            temp_v_reg = (~temp_v) & 0x7FFF;
        }

        Reg_VP2[Count_VP2++] = (float)temp_v_reg/32767*1.225f*6452.61f;// *Load_VP
        if(Count_VP2>=Filter_Num)/*数组地址*/
            Count_VP2 = 0;
        
        total_v1 = 0;       
        for(i=0;i<Filter_Num;i++)
            total_v1 += Reg_VP2[i];  

        *Load_VP = total_v1/Filter_Num;

    }
}

/**
*******************************************************
*@brief 采集负string的电池侧电压值、负荷侧电压值
*@param[in]   none
*@param[out]   REG_VP:正string的电池电压指针
*@param[out]   Load_VN:正string的负载电压指针
*@return  none
*@note    none
*******************************************************
*/
void Rack_VN_Read(u16 *REG_VP,float* Load_VN)
{
    u8 datatemp[10];
    u16 temp_v,temp_i,temp_i_reg,temp_v_reg;
    float total_v1;
    u8 i;

    AS8510_VB_Read(datatemp,0x84,0x01);        /*电压采集*/ 
    delay_us(15);
	
	/*根据采集的数值，进行相位换算，并进行相位处理*/
    if((datatemp[0]&0x80) != 0)
    {
        AS8510_VB_Read(datatemp,0x80,0x04);                   
        temp_i = datatemp[0]<<8|datatemp[1];
        if((datatemp[0]&0x80)!=0)
        {
            temp_i_reg = (temp_i) & 0x7FFF;
            Reg_VN1[Count_VN1++] = (float)temp_i_reg/32767*1.225f*6452.61f;//32767*1.225f*6666.67f;  //500A，75mv
        }
        else
        {
            temp_i_reg = (~temp_i) & 0x7FFF;
            Reg_VN1[Count_VN1++] = (float)temp_i_reg/32767*1.225f*6452.61f;//32767*1.225f*6666.67f;  //500A，75mv
        }
        
        if(Count_VN1>=Filter_Num)/*数组地址*/
            Count_VN1 = 0;
        
        total_v1 = 0;       
        for(i=0;i<Filter_Num;i++)
            total_v1 += Reg_VN1[i]; 
        
        *REG_VP = (u16)(total_v1/Filter_Num);
		
		temp_v = datatemp[2] << 8 | datatemp[3];

        if ((datatemp[2] & 0x80) != 0)
            temp_v_reg = (temp_v) & 0x7FFF;
        else
        {
            temp_v_reg = (~temp_v) & 0x7FFF;
        }
		Reg_VN2[Count_VN2++] = (float)temp_v_reg/32767*1.225f*6452.61f;// *Load_VP  *0.76f是系数，怀疑采样电阻有微小偏差万用表不能测出
        
        if(Count_VN2>=Filter_Num)/*数组地址*/
            Count_VN2 = 0;
        
        total_v1 = 0;       
        for(i=0;i<Filter_Num;i++)
            total_v1 += Reg_VN2[i]; 

        *Load_VN = total_v1/Filter_Num;

     }
}

/** 
*******************************************************
*@brief 采集正string的电流值
*@param[in]   none
*@param[out]   REG_IP:正string的电流指针
*@return  none
*@note    none
*******************************************************
*/
void Rack_IP_Read(s16 *REG_IP)
{
    u8 datatemp[10];
    s16 temp_i, temp_i_reg;
    float total_ip;	/*正string的电流*/
    u8 i;
		
    AS8510_I_Read(datatemp, 0x84, 0x01);                
    delay_us(10);
	
	/*电流幅值和相位的处理*/
    if ((datatemp[0] & 0x80) != 0)
    {
        AS8510_I_Read(datatemp, 0x80, 0x04);                
        temp_i = datatemp[0] << 8 | datatemp[1];

        if ((datatemp[0] & 0x80) != 0)	/*检测电流是否是负数，采取不同的处理方法*/
        {
            temp_i_reg = (temp_i) & 0x7FFF;
            Reg_IP[Count_IP++] = (float) temp_i_reg / 32767 * 1.225f * 6666.67f;   //500A，75mv
        }
        else
        {
            temp_i_reg = (~temp_i) & 0x7FFF;
            Reg_IP[Count_IP++] = 0 - (float) temp_i_reg / 32767 * 1.225f * 6666.67f;   //500A，75mv
        }

        if(Count_IP>=Filter_Num)/*数组地址*/
            Count_IP = 0;
        
        total_ip = 0;       
        for(i=0;i<Filter_Num;i++)
            total_ip += Reg_IP[i]; 
        
        *REG_IP = (s16) (total_ip/Filter_Num);
    }
}

/** 
*******************************************************
*@brief 采集负string的电流值
*@param[in]   none
*@param[out]   REG_IN:负string的电流指针
*@return  none
*@note    none
*******************************************************
*/
void Rack_IN_Read(s16 *REG_IN)
{
    u8 datatemp[10];
    s16 temp_i, temp_i_reg;
	float total_in;	/*负string的电流*/
    u8 i;
	

    AS8510_Ins_Read(datatemp, 0x84, 0x01);                  
    delay_us(10);

    if ((datatemp[0] & 0x80) != 0)
    {
        AS8510_Ins_Read(datatemp, 0x80, 0x04);                  
		temp_i = datatemp[2] << 8 | datatemp[3];
		if ((datatemp[2] & 0x80) != 0)
        {
            temp_i_reg = (temp_i) & 0x7FFF;
			Reg_IN[Count_IN++]= (float) temp_i_reg / 32767 * 1.225f * 6666.67f;   //500A，75mv
        }
        else
        {
            temp_i_reg = (~temp_i) & 0x7FFF;
			Reg_IN[Count_IN++] = 0 - (float) temp_i_reg / 32767 * 1.225f * 6666.67f;   //500A，75mv
        }        
        
        if(Count_IN>=Filter_Num)/*数组地址*/
            Count_IN = 0;
        
        total_in = 0;       
        for(i=0;i<Filter_Num;i++)
            total_in += Reg_IN[i]; 

		*REG_IN = (s16)(total_in/Filter_Num);
    }
}

/** 
*******************************************************
*@brief SPI在指定地址开始读取指定长度的数据（此处主要是正电压）
*@param[in]    ReadAddr:开始读取的地址(24bit)
*@param[in]    NumByteToRead:要读取的字节数(最大65535)
*@param[out]   pBuffer:数据存储区
*@return  none
*@note    none
*******************************************************
*/
void AS8510_V_Read(u8 *pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
    u16 i;
    AS5810_VP_CS = CS_EN;                          //使能器件
    SPI2_ReadWriteByte((u8) ReadAddr);

    for (i = 0; i < NumByteToRead; i++)
    {
        pBuffer[i] = SPI2_ReadWriteByte(0XFF);    //循环读数
    }

    AS5810_VP_CS = CS_DIS;
}

/** 
*******************************************************
*@brief SPI在指定地址开始读取指定长度的数据（此处主要是负电压）
*@param[in]    ReadAddr:开始读取的地址(24bit)
*@param[in]    NumByteToRead:要读取的字节数(最大65535)
*@param[out]   pBuffer:数据存储区
*@return  none
*@note    none
*******************************************************
*/
void AS8510_VB_Read(u8 *pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
    u16 i;
    AS5810_VN_CS = CS_EN;                          //使能器件
    SPI4_ReadWriteByte((u8) ReadAddr);

    for (i = 0; i < NumByteToRead; i++)
    {
        pBuffer[i] = SPI4_ReadWriteByte(0XFF);    //循环读数
    }

    AS5810_VN_CS = CS_DIS;
}

/** 
*******************************************************
*@brief SPI对采样芯片进行设计
*@param[in]    none
*@return  none
*@note    none
*******************************************************
*/
void AS8510_V_Write()
{
    AS5810_VP_CS = CS_EN;
    SPI2_ReadWriteByte((u8) W_COM_DRESS1);
    SPI2_ReadWriteByte((u8) DEC_REG_R1_I);
    SPI2_ReadWriteByte((u8) DEC_REG_R2_I);
    SPI2_ReadWriteByte((u8) FIR_CTL_REG_I);
    SPI2_ReadWriteByte((u8) CLK_REG);
    SPI2_ReadWriteByte((u8) RESET_REG);
    SPI2_ReadWriteByte((u8) MOD_CTL_REG);
    AS5810_VP_CS = CS_DIS;
    delay_ms(1);
    AS5810_VP_CS = CS_EN;
    SPI2_ReadWriteByte(W_COM_DRESS3);       //设定初始采样增益为5
    SPI2_ReadWriteByte(PGA_CTL_REG);
    SPI2_ReadWriteByte(PD_CTL_REG_1);
    SPI2_ReadWriteByte(PD_CTL_REG_2);
    AS5810_VP_CS = CS_DIS;
    delay_ms(1);
    AS5810_VP_CS = CS_EN;
    SPI2_ReadWriteByte((u8) W_COM_DRESS2);
    SPI2_ReadWriteByte((u8) DEC_REG_R1_V);
    SPI2_ReadWriteByte((u8) DEC_REG_R2_V);
    SPI2_ReadWriteByte((u8) FIR_CTL_REG_V);
    AS5810_VP_CS = CS_DIS;
}
/** 
*******************************************************
*@brief SPI对采样芯片进行设计
*@param[in]    none
*@return  none
*@note    none
*******************************************************
*/
void AS8510_VB_Write()
{
    AS5810_VN_CS = CS_EN;
    SPI4_ReadWriteByte((u8) W_COM_DRESS1);
    SPI4_ReadWriteByte((u8) DEC_REG_R1_I);
    SPI4_ReadWriteByte((u8) DEC_REG_R2_I);
    SPI4_ReadWriteByte((u8) FIR_CTL_REG_I);
    SPI4_ReadWriteByte((u8) CLK_REG);
    SPI4_ReadWriteByte((u8) RESET_REG);
    SPI4_ReadWriteByte((u8) MOD_CTL_REG);
    AS5810_VN_CS = CS_DIS;
    delay_ms(1);
    AS5810_VN_CS = CS_EN;
    SPI4_ReadWriteByte(W_COM_DRESS3);       //设定初始采样增益为5
    SPI4_ReadWriteByte(PGA_CTL_REG);
    SPI4_ReadWriteByte(PD_CTL_REG_1);
    SPI4_ReadWriteByte(PD_CTL_REG_2);
    AS5810_VN_CS = CS_DIS;
    delay_ms(1);
    AS5810_VN_CS = CS_EN;
    SPI4_ReadWriteByte((u8) W_COM_DRESS2);
    SPI4_ReadWriteByte((u8) DEC_REG_R1_V);
    SPI4_ReadWriteByte((u8) DEC_REG_R2_V);
    SPI4_ReadWriteByte((u8) FIR_CTL_REG_V);
    AS5810_VN_CS = CS_DIS;
}

/** 
*******************************************************
*@brief SPI在指定地址开始读取指定长度的数据（此处主要是正电流）
*@param[in]    ReadAddr:开始读取的地址(24bit)
*@param[in]    NumByteToRead:要读取的字节数(最大65535)
*@param[out]   pBuffer:数据存储区
*@return  none
*@note    none
*******************************************************
*/
void AS8510_I_Read(u8 *pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
    u16 i;
    AS5810_IP_CS = CS_EN;                          //使能器件
    SPI5_ReadWriteByte((u8) ReadAddr);

    for (i = 0; i < NumByteToRead; i++)
    {
        pBuffer[i] = SPI5_ReadWriteByte(0XFF);    //循环读数
    }

    AS5810_IP_CS = CS_DIS;
}

/** 
*******************************************************
*@brief SPI在指定地址开始读取指定长度的数据（此处主要是负电流）
*@param[in]    ReadAddr:开始读取的地址(24bit)
*@param[in]    NumByteToRead:要读取的字节数(最大65535)
*@param[out]   pBuffer:数据存储区
*@return  none
*@note    none
*******************************************************
*/
void AS8510_Ins_Read(u8 *pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
    u16 i;
    AS5810_IN_CS = CS_EN;                          //使能器件
    SPI6_ReadWriteByte((u8) ReadAddr);

    for (i = 0; i < NumByteToRead; i++)
    {
        pBuffer[i] = SPI6_ReadWriteByte(0XFF);    //循环读数
    }

    AS5810_IN_CS = CS_DIS;
}
/** 
*******************************************************
*@brief SPI对采样芯片进行设计
*@param[in]    none
*@return  none
*@note    none
*******************************************************
*/
void AS8510_I_Write()
{
    AS5810_IP_CS = CS_EN;
    SPI5_ReadWriteByte((u8) W_COM_DRESS1);
    SPI5_ReadWriteByte((u8) DEC_REG_R1_I);
    SPI5_ReadWriteByte((u8) DEC_REG_R2_I);
    SPI5_ReadWriteByte((u8) FIR_CTL_REG_I);
    SPI5_ReadWriteByte((u8) CLK_REG);
    SPI5_ReadWriteByte((u8) RESET_REG);
    SPI5_ReadWriteByte((u8) MOD_CTL_REG);
    AS5810_IP_CS = CS_DIS;
    delay_ms(1);
    AS5810_IP_CS = CS_EN;
    SPI5_ReadWriteByte(W_COM_DRESS3);       //设定初始采样增益为5
    SPI5_ReadWriteByte(PGA_CTL_REG);
    SPI5_ReadWriteByte(PD_CTL_REG_1);
    SPI5_ReadWriteByte(PD_CTL_REG_2);     //后修改为电流增加
//    SPI2_ReadWriteByte(PD_CTL_REG_2);
//    SPI2_ReadWriteByte(PD_CTL_REG_3);
    AS5810_IP_CS = CS_DIS;
    delay_ms(1);
    AS5810_IP_CS = CS_EN;
    SPI5_ReadWriteByte((u8) W_COM_DRESS2);
    SPI5_ReadWriteByte((u8) DEC_REG_R1_V);
    SPI5_ReadWriteByte((u8) DEC_REG_R2_V);
    SPI5_ReadWriteByte((u8) FIR_CTL_REG_V);
    AS5810_IP_CS = CS_DIS;
}
/** 
*******************************************************
*@brief SPI对采样芯片进行设计
*@param[in]    none
*@return  none
*@note    none
*******************************************************
*/
void AS8510_Ins_Write()
{
    AS5810_IN_CS = CS_EN;
    SPI6_ReadWriteByte((u8) W_COM_DRESS1);
    SPI6_ReadWriteByte((u8) DEC_REG_R1_I);
    SPI6_ReadWriteByte((u8) DEC_REG_R2_I);
    SPI6_ReadWriteByte((u8) FIR_CTL_REG_I);
    SPI6_ReadWriteByte((u8) CLK_REG);
    SPI6_ReadWriteByte((u8) RESET_REG);
    SPI6_ReadWriteByte((u8) MOD_CTL_REG);
    AS5810_IN_CS = CS_DIS;
    delay_ms(1);
    AS5810_IN_CS = CS_EN;
    SPI6_ReadWriteByte(W_COM_DRESS3);       //设定初始采样增益为5
    SPI6_ReadWriteByte(PGA_CTL_REG);
    SPI6_ReadWriteByte(PD_CTL_REG_1);
    SPI6_ReadWriteByte(PD_CTL_REG_2);     //后修改为电流增加
//    SPI2_ReadWriteByte(PD_CTL_REG_2);
//    SPI2_ReadWriteByte(PD_CTL_REG_3);
    AS5810_IN_CS = CS_DIS;
    delay_ms(1);
    AS5810_IN_CS = CS_EN;
    SPI6_ReadWriteByte((u8) W_COM_DRESS2);
    SPI6_ReadWriteByte((u8) DEC_REG_R1_V);
    SPI6_ReadWriteByte((u8) DEC_REG_R2_V);
    SPI6_ReadWriteByte((u8) FIR_CTL_REG_V);
    AS5810_IN_CS = CS_DIS;
}
